package com.siyoumi.app.modules.app_ess.web;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.siyoumi.app.entity.*;
import com.siyoumi.app.modules.app_ess.entity.EnumEssFileType;
import com.siyoumi.app.modules.app_ess.service.*;
import com.siyoumi.app.modules.app_ess.vo.*;
import com.siyoumi.app.modules.user.service.SvcSysUser;
import com.siyoumi.app.service.EssClassUserService;
import com.siyoumi.app.service.EssStudyRecordService;
import com.siyoumi.app.sys.entity.AesKi;
import com.siyoumi.app.sys.service.SvcSysUv;
import com.siyoumi.app.sys.vo.VoUvSave;
import com.siyoumi.component.XApp;
import com.siyoumi.component.XBean;
import com.siyoumi.component.XEnumBase;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.config.SysConfig;
import com.siyoumi.controller.WxAppApiController;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XJson;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/wxapp/app_ess/api")
public class ApiAppEss
        extends WxAppApiController {

    /**
     * 初始化
     *
     * @return
     */
    @GetMapping("init")
    public XReturn init() {
        EssUser entityUser = SvcEssUser.getBean().getEntity(getUid());
        Map<String, Object> mapUser = XBean.toMap(entityUser, new String[]{
                "euser_type",
                "euser_sex",
                "euser_speciality",
                "euser_school_date",
                "euser_contact",
                "euser_address",
                "euser_model_count",
                "euser_model_fun",
                "euser_file_count",
                "euser_file_fun",
                "euser_test0_count",
                "euser_test0_fun",
                "euser_test1_count",
                "euser_test1_fun",
        });
        SysUser entitySysUser = SvcSysUser.getBean().getEntity(getUid());
        mapUser.put("user_id", entitySysUser.getUser_id());
        mapUser.put("user_name", entitySysUser.getUser_name());
        mapUser.put("user_username", entitySysUser.getUser_username());
        mapUser.put("user_headimg", entitySysUser.getUser_headimg());
        mapUser.put("user_fun", entitySysUser.getUser_fun());

        getR().put("user", mapUser);
        //所属班级
        getR().put("list_class", SvcEssClass.getBean().getList(getUid()));
        getR().setData("setting", SvcEssSetting.getBean().getSetting()); //设置

        return getR();
    }

    /**
     * 更新用户资料
     *
     * @param vo
     * @param result
     */
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/user_edit")
    public XReturn userEdit(@Validated VoEssUserEdit vo, BindingResult result) {
        //统一验证
        XValidator.getResult(result, true);

        EssUser entityUpdate = new EssUser();
        XBean.copyProperties(vo, entityUpdate);
        entityUpdate.setEuser_id(getUid());
        SvcEssUser.getApp().updateById(entityUpdate);
        SvcEssUser.getApp().delEntityCache(getUid());

        if (XStr.hasAnyText(vo.getUser_headimg())) {
            SysUser entitySysUserUpdate = new SysUser();
            XBean.copyProperties(vo, entitySysUserUpdate);
            entitySysUserUpdate.setUser_id(getUid());
            SvcSysUser.getApp().updateById(entitySysUserUpdate);
            SvcSysUser.getApp().delEntityCache(getUid());
        }

        return EnumSys.OK.getR();
    }

    //模块列表
    @GetMapping("module_list")
    public XReturn moduleList() {
        InputData inputData = InputData.fromRequest();

        String[] select = {
                "emod_id",
                "emod_name",
                "emod_pic",
                "emod_set_task_total",
                "emod_exe_tag",
                "emod_test_id",
                "emod_enable",
                "emod_question0",
                "emod_question1",
        };
        JoinWrapperPlus<EssModule> query = SvcEssModule.getBean().listQuery(inputData);
        query.eq("emod_enable", 1);
        query.select(select);

        IPage<EssModule> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), false);
        //list
        IPage<Map<String, Object>> pageData = SvcEssModule.getApp().getMaps(page, query);
        List<Map<String, Object>> list = pageData.getRecords();
        for (Map<String, Object> item : list) {
        }

        getR().put("list", list);

        return getR();
    }

    //资源列表
    @GetMapping("file_list")
    public XReturn fileList() {
        InputData inputData = InputData.fromRequest();
        String moduleId = inputData.input("module_id");
        XValidator.isNullOrEmpty(moduleId, "miss module_id");

        String[] select = {
                "efile_id",
                "efile_name",
                "efile_type",
                "efile_type_sys",
                "efile_path",
                "efile_file_size",
                "efile_file_ext",
                "efile_collect_count",
                "efile_order",
        };
        JoinWrapperPlus<EssFile> query = SvcEssFile.getBean().listQuery(inputData);
        query.select(select);

        IPage<EssFile> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), true);
        //list
        IPage<Map<String, Object>> pageData = SvcEssFile.getApp().getMaps(page, query);
        List<Map<String, Object>> list = pageData.getRecords();

        List<String> fileIds = list.stream().map(item -> (String) item.get("efile_id")).collect(Collectors.toList());
        List<String> collectIds = SvcSysUv.getBean().getTypeIds(fileIds, "file", getUid()); //收藏

        for (Map<String, Object> item : list) {
            EssFile entity = XBean.fromMap(item, EssFile.class);
            //访问路径
            item.put("file_url", XApp.fileUrl(entity.getEfile_path()));
            //收藏
            item.put("is_collect", collectIds.contains(entity.getKey()));
        }

        getR().setData("list", list);
        getR().setData("total", pageData.getTotal());

        EnumEssFileType enumFileType = XEnumBase.of(EnumEssFileType.class);
        getR().put("file_type", enumFileType);
        return getR();
    }

    /**
     * 学习任务列表
     */
    @GetMapping("study_list")
    public XReturn studyList() {
        InputData inputData = InputData.fromRequest();
        String moduleId = inputData.input("module_id");
        XValidator.isNullOrEmpty(moduleId, "miss module_id");

        String[] select = {
                "estudy_id",
                "estudy_name",
                "estudy_date_begin",
                "estudy_date_end",
        };
        JoinWrapperPlus<EssStudy> query = SvcEssStudy.getBean().listQuery(inputData);
        String sqlExists = "SELECT 1 FROM wx_app_x.t_ess_study_student WHERE esstu_study_id = estudy_id AND esstu_uid = {0}";
        query.exists(sqlExists, getUid());
        query.select(select);
        query.orderByDesc("estudy_create_date")
                .orderByAsc("estudy_id");

        IPage<EssStudy> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), true);
        //list
        IPage<Map<String, Object>> pageData = SvcEssStudy.getApp().getMaps(page, query);
        List<Map<String, Object>> list = pageData.getRecords();
        //收集所有ID
        List<String> estudyIds = list.stream().map(item -> (String) item.get("estudy_id"))
                .collect(Collectors.toList());
        List<Map<String, Object>> listRecord = SvcEssStudy.getBean().getRecordList(estudyIds, getUid()); //子任务列表
        //
        for (Map<String, Object> item : list) {
            EssStudy entity = XBean.fromMap(item, EssStudy.class);
            item.put("id", entity.getKey());
            item.put("state", SvcEssStudy.getBean().getState(entity));
            //学生完成记录
            List<Map<String, Object>> record = listRecord.stream().filter(i -> i.get("esre_study_id").equals(entity.getKey()))
                    .collect(Collectors.toList());
            item.put("record", record);
        }

        getR().setData("total", pageData.getTotal());
        getR().setData("list", list);

        return getR();
    }

    /**
     * 学习任务完成
     */
    @PostMapping("study_task_done")
    public XReturn studyTaskDone(@Validated @RequestBody VoEssStudyTaskDone vo, BindingResult result) {
        //统一验证
        XValidator.getResult(result, true);
        //
        return SvcEssStudy.getBean().studyTaskDone(vo);
    }

    /**
     * 学习任务-实训详情
     */
    @GetMapping("study_record_info")
    public XReturn studyRecordInfo() {
        InputData inputData = InputData.fromRequest();
        String recordId = inputData.input("record_id");
        XValidator.isNullOrEmpty(recordId, "miss record_id");

        EssStudyRecord entityRecord = EssStudyRecordService.getBean().getEntity(recordId);
        XValidator.isNull(entityRecord, "record_id error");
        if (!"test1".equals(entityRecord.getEsre_task_key())) {
            return EnumSys.MISS_VAL.getR("非理论实训任务");
        }
        if (entityRecord.getEsre_state() != 1) {
            return EnumSys.MISS_VAL.getR("理论实训任务未完成");
        }
        Map<String, Object> mapRecord = XBean.toMap(entityRecord, new String[]{
                "esre_id",
                "esre_task_key",
                "esre_fun",
                "esre_state",
                "esre_state_date",
        });
        VoEssStudyTaskDoneJson json = new VoEssStudyTaskDoneJson(); //答案结果
        if (XStr.hasAnyText(entityRecord.getEsre_state_json())) {
            json = XJson.parseObject(entityRecord.getEsre_state_json(), VoEssStudyTaskDoneJson.class);
        }
        mapRecord.put("submit_minute", json.getSubmit_minute());
        getR().setData("record", mapRecord);
        List<String> questionIds = json.getItems().stream().map(item -> item.getQuestion_id()).collect(Collectors.toList());
        if (questionIds.isEmpty()) {
            questionIds = List.of("x"); //为了不报sql错误
        }
        //题目处理
        String[] select = {
                "etqu_id",
                "etqu_type",
                "etqu_question_type",
                "etqu_question",
                "etqu_question_item",
                "etqu_level",
                "etqu_answer",
        };
        inputData.put("all", "1");
        JoinWrapperPlus<EssQuestion> query = SvcEssQuestion.getBean().listQuery(inputData);
        query.select(select);
        query.in("etqu_id", questionIds);
        query.orderByAsc("etqu_order")
                .orderByAsc("etqu_id");

        List<Map<String, Object>> listQuestion = SvcEssQuestion.getApp().getMaps(query);
        for (Map<String, Object> item : listQuestion) {
            String questionId = (String) item.get("etqu_id");
            //用户答案
            VoEssStudyTaskDoneJsonItem userQuestionItem = json.getItems().stream().filter(i -> i.getQuestion_id().equals(questionId)).findFirst().orElse(null);
            String answer = "";//用户答案
            if (userQuestionItem != null) {
                answer = XJson.toJSONString(userQuestionItem.getQuestion_answer());
            }
            item.put("user_answer", answer);
        }
        getR().setData("question", listQuestion);

        //用户
        SysUser entityUser = SvcSysUser.getBean().getEntity(entityRecord.getEsre_uid());
        Map<String, Object> mapUser = XBean.toMap(entityUser, new String[]{
                "user_id",
                "user_name",
        });
        getR().setData("user", mapUser);
        //班级
        EssClass entityClass = SvcEssClass.getApp().getEntity(entityRecord.getEsre_class_id());
        Map<String, Object> mapClass = XBean.toMap(entityClass, new String[]{
                "eclass_id",
                "eclass_name",
        });
        getR().setData("class", mapClass);

        return getR();
    }

    /**
     * 评测列表
     */
    @GetMapping("test_list")
    public XReturn testList() {
        InputData inputData = InputData.fromRequest();

        String[] select = {
                "etest_id",
                "etest_title",
                "etest_date_begin",
                "etest_date_end",
                "etest_fun_total",
                "etest_state",
                "etest_state_date",
                "etres_id",
                "etest_test_not_submit",
                "etres_submit",
                "etres_submit_minute",
                "etres_test_fun",
                "etres_submit_date_end",
                "etres_send_fun",
        };
        JoinWrapperPlus<EssTest> query = SvcEssTest.getBean().listQuery(inputData);
        query.join(EssTestResult.table(), EssTest.tableKey(), "etres_test_id");
        query.eq("etres_uid", getUid()); //指定老师
        query.orderByDesc("etest_id");
        query.select(select);
        IPage<EssTest> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), true);
        //list
        IPage<Map<String, Object>> pageData = SvcEssTest.getApp().getMaps(page, query);
        List<Map<String, Object>> list = pageData.getRecords();
        for (Map<String, Object> item : list) {
            EssTest entity = XBean.fromMap(item, EssTest.class);
            EssTestResult entityResult = XBean.fromMap(item, EssTestResult.class);
            item.put("id", entity.getKey());
            //状态
            XReturn rState = SvcEssTest.getBean().getState(entity);
            item.put("state", rState);
            //离结束还剩余X分钟
            item.put("date_end_left_minute", entity.dateEndLeftMinute());
            //提交剩余X秒
            item.put("submit_left_second", entityResult.submitLeftSecond());
        }

        getR().setData("list", list);
        getR().setData("total", pageData.getTotal());

        return getR();
    }

    /**
     * 评价开始
     */
    @PostMapping("test_start")
    public XReturn testStart(@Validated VoEssTestStartTest vo, BindingResult result) {
        //统一验证
        XValidator.getResult(result, true);
        //
        return SvcEssTest.getBean().startTest(vo);
    }

    /**
     * 评价提交答案
     */
    @PostMapping("test_answer")
    public XReturn testAnswer(@Validated @RequestBody VoEssTestAnswer vo, BindingResult result) {
        //统一验证
        XValidator.getResult(result, true);
        //
        for (int i = 0; i < vo.getItems().size(); i++) {
            if (vo.getItems().get(i).getAnswer() == null || vo.getItems().get(i).getAnswer().stream().anyMatch(item -> item == null)) {
                XValidator.err(20387, "提交答案不能为null，下标" + i);
            }
        }
        //
        return SvcEssTest.getBean().answer(vo);
    }

    /**
     * 题库
     */
    @GetMapping("question_list")
    public XReturn questionList() {
        InputData inputData = InputData.fromRequest();
        String moduleIdInput = inputData.input("module_id");
        boolean errorRank = "1".equals(inputData.input("error_rank")); //错题榜
        EssUser entityUser = SvcEssUser.getBean().getEntity(getUid());

        String[] select = {
                "etqu_id",
                "etqu_type",
                "etqu_module_id",
                "etqu_question_type",
                "etqu_question",
                "etqu_question_item",
                "etqu_level",
                "etqu_answer",
                "etqu_level",
                "etqu_answer_total",
                "etqu_answer_bingo_total",
                "etqu_answer_error_total",
                "etqu_order",
                "emod_id",
                "emod_name",
        };
        JoinWrapperPlus<EssQuestion> query = SvcEssQuestion.getBean().listQuery(inputData);
        query.join(EssModule.table(), EssModule.tableKey(), "etqu_module_id");
        query.select(select);
        if (!SvcEssUser.getBean().isTeacher(entityUser)) {
            query.eq("etqu_type", 1);
        }
        if (errorRank) { //错题榜
            query.gt("etqu_answer_error_total", 0);
            query.orderByDesc("etqu_answer_error_total")
                    .orderByAsc("etqu_id");
        } else {
            query.orderByAsc("etqu_order")
                    .orderByAsc("etqu_id");
        }

        IPage<EssQuestion> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), true);
        if (XStr.hasAnyText(moduleIdInput)) {
            page = new Page<>(inputData.getPageIndex(), 5000, true);
        }
        //list
        IPage<Map<String, Object>> pageData = SvcEssQuestion.getApp().getMaps(page, query);
        List<Map<String, Object>> list = pageData.getRecords();
        //
        Map<String, Object> mapModule = new HashMap<>();
        for (Map<String, Object> item : list) {
            String moduleId = (String) item.get("emod_id");
            String moduleName = (String) item.get("emod_name");
            mapModule.put(moduleId, moduleName);
        }
        //
        for (Map<String, Object> item : list) {
            EssQuestion entity = XBean.fromMap(item, EssQuestion.class);
            item.put("id", entity.getKey());
        }

        getR().setData("list", list);
        getR().setData("count", pageData.getTotal());
        getR().setData("module", mapModule);
        return getR();
    }


    /**
     * 积分排行榜
     */
    @GetMapping("user_list")
    public XReturn userList() {
        InputData inputData = InputData.fromRequest();

        SysUser entityUser = SvcSysUser.getBean().getEntity(getUid());

        String[] select = {
                "user_id",
                "user_name",
                "user_update_date",
                "user_fun",
                "euser_test1_count",
                "euser_module_count",
        };
        JoinWrapperPlus<EssUser> query = SvcEssUser.getBean().listQuery(inputData);
        query.gt("user_fun", 0)
                .eq("euser_type", 0);
        query.select(select);
        query.orderByDesc("user_fun")
                .orderByAsc("user_update_date");
        Long rankIndex = -1L;
        //用户排名
        if (entityUser.getUser_fun() > 0) {
            JoinWrapperPlus<EssUser> queryRank = query.cloneJoinPlus();
            queryRank.and(
                    q -> q.gt("user_fun", entityUser.getUser_fun())
                            .or(qq -> qq.eq("user_fun", entityUser.getUser_fun())
                                    .lt("user_update_date", entityUser.getUser_update_date())
                            )
            );
            rankIndex = SvcEssUser.getApp().count(queryRank);
        }

        IPage<EssUser> page = new Page<>(inputData.getPageIndex(), inputData.getPageSize(), false);
        //list
        IPage<Map<String, Object>> pageData = SvcEssUser.getApp().getMaps(page, query);
        List<Map<String, Object>> list = pageData.getRecords();
        //
        for (Map<String, Object> item : list) {
        }

        getR().setData("list", list);
        getR().setData("rank_index", rankIndex); //积分排序
        getR().setData("setting", SvcEssSetting.getBean().getSetting()); //设置
        return getR();
    }

    /**
     * 积分任务
     */
    @PostMapping("task_fun")
    public XReturn taskFun(@Validated @RequestBody VaTaskFun vo, BindingResult result) {
        //统一验证
        XValidator.getResult(result, true);
        //
        if (!SysConfig.getBean().isDev()) {
            AesKi ki = AesKi.of(XHttpContext.getXConfig().getAconfig_token());
            Long apiTime = XStr.toLong(ki.decTxt(vo.getTime()));
            Long timeLong = XDate.toS() - apiTime;
            if (Math.abs(timeLong) > 300) {
                return EnumSys.ERR_VAL.getR("接口异常时间异常");
            }
        }

        vo.setModule_id(vo.getModule_id());
        vo.setType(vo.getType());
        vo.setUid(getUid());
        return SvcEssSetting.getBean().taskFun(vo);
    }


    /**
     * 用户收藏
     */
    @PostMapping("collect")
    @Transactional(rollbackFor = Exception.class)
    public XReturn collect(@Validated VoUvSave vo, BindingResult result) {
        XValidator.isNullOrEmpty(vo.getType_id(), "miss type_id");
        List<String> types = List.of("file");
        if (!types.contains(vo.getType())) {
            result.addError(XValidator.getErr("type", "请输入指定值：" + types));
        }
        //
        XValidator.getResult(result, true, true);

        vo.setApp_id("app_ess");
        vo.setUid(getUid());
        XReturn r = SvcSysUv.getBean().save(vo);
        if (r.ok()) {
            if ("file".equals(vo.getType())) {
                //更新总数
                SvcEssFile.getBean().updateCollect(vo.getType_id());
            }
        }

        return r;
    }
}
